import LayerBase, { getLayerId } from "@/core/layers/base"
import { CanvasContextType } from "../public"


type Options = Pick<LayerSelection, 'name' | 'ctxType'> & Partial<Pick<LayerSelection, 'x1' | 'y1' | 'x2' | 'y2' | 'animation'>>


export type DrawStrokeRectOptions = {
  strokeStyle?: string
  lineWidth?: number
  lineDashOffset?: number
  lineDashOffsetAutoIncrement?: number
  lineDashSegments?: number[]
}



export default class LayerSelection extends LayerBase {
  id = getLayerId()
  name: string
  ctxType: CanvasContextType
  readonly layerType = 'selection'
  
  x1: number
  y1: number
  x2: number
  y2: number
  animation: boolean
  
  private lineDashOffsetTotal = 0;


  constructor(options: Options){
    super()
    this.name = options.name
    this.ctxType = options.ctxType
    this.x1 = options.x1 !== undefined ? options.x1 : 0
    this.y1 = options.y1 !== undefined ? options.y1 : 0
    this.x2 = options.x2 !== undefined ? options.x2 : 0
    this.y2 = options.y2 !== undefined ? options.y2 : 0
    this.animation = options.animation !== undefined ? options.animation : true
  }

  render(ctx: CanvasRenderingContext2D){
    if(!this.offscreenCanvasCtx) return false

    const width = Math.abs(this.x1 - this.x2);
    const height = Math.abs(this.y1 - this.y2);

    if(height == 0 || width == 0) return false

    if(!this.rendered){
      this.offscreenCanvasCtx.canvas.width = width
      this.offscreenCanvasCtx.canvas.height = height
      this.drawStrokeRect(this.offscreenCanvasCtx, 0, 0, width, height)
      this.rendered = !this.animation
    }

    ctx.globalAlpha = this.opacity
    ctx.drawImage(this.offscreenCanvasCtx.canvas, Math.min(this.x1, this.x2), Math.min(this.y1, this.y2))
    return this.animation
  }

  drawStrokeRect = (ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number, options?: DrawStrokeRectOptions) => {
    const mergeOptions = {
      strokeStyle: '#ccc',
      lineWidth: 1,
      lineDashOffset: 5,
      lineDashSegments: [5, 5],
      lineDashOffsetAutoIncrement: 0.04,
      ...options
    }
  
    const incrementCycle = mergeOptions.lineDashSegments.reduce((total, item) => total += item, 0);
  
    ctx.beginPath()
    if(mergeOptions.strokeStyle) ctx.strokeStyle = mergeOptions.strokeStyle
    if(mergeOptions.lineWidth) ctx.lineWidth = mergeOptions.lineWidth
    if(mergeOptions.lineDashOffsetAutoIncrement) {
      this.lineDashOffsetTotal = (this.lineDashOffsetTotal + mergeOptions.lineDashOffsetAutoIncrement) % incrementCycle;
      ctx.lineDashOffset = this.lineDashOffsetTotal
    }
    else if(mergeOptions.lineDashOffset) ctx.lineDashOffset = this.lineDashOffsetTotal
  
    if(mergeOptions.lineDashSegments) ctx.setLineDash(mergeOptions.lineDashSegments)
    ctx.strokeRect(x, y, width, height)
  }

  serialize(){
    return {
      id: this.id,
      name: this.name,
      ctxType: this.ctxType,
      layerType: this.layerType,
      x1: this.x1,
      y1: this.y1,
      x2: this.x2,
      y2: this.y2,
      animation: this.animation,
      opacity: this.opacity,
      visible: this.visible,
    }
  }
}